home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
forlib1.arc
/
DOW.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-01-16
|
10KB
|
228 lines
DATA SEGMENT PUBLIC 'DATA'
TITLE__ DB 'TITLE: DAY OF WEEK FOR MS FORTRAN'
COPY_R DB ' (C) John R. Petrocelli'
DB ' Schenectady,NY '
DB ' 01/16/86 '
INITIAL_YEAR EQU 1901 ; 1901 INITIAL YEAR
INITIAL_DAY EQU 3-1 ; TUESDAY 01/01/1901 CORRECTED
; (-1) FOR COMPUTATION SINCE WE
; MUST START WITH 0
MAX_YEAR EQU 2099 ; HIGHEST YEAR WE CAN CALCULATE
; FOR THIS ROUTINE
; *** NOTE ***
; A CENTURY IS ONLY A LEAP YEAR
; IF IT IS EVENLY DIVISIBLE BY
; 400. THEREFORE THE YEAR 2000
; IS A LEAP YEAR.
LEAP_YEAR_OFF EQU 0
LEAP_YEAR_ON EQU 1
CR EQU 0DH ; CARRAGE RETURN
LF EQU 0AH ; LINE FEED
EOM EQU '$' ; END OF MESSAGE INDICATOR
ERR_MSG_HDR DB CR,LF,'WEEKDY SUBROUTINE PARAMETER ERROR',EOM
ERR_MSG_YR DB CR,LF,'YEAR MUST BE > 1901 AND < 2099',CR,LF,EOM
ERR_MSG_MO DB CR,LF,'MONTH LESS THAN 1 OR GREATER THAN 12',CR,LF,EOM
ERR_MSG_DY DB CR,LF,'DAY LESS THAN 1 OR GREATER '
DB CR,LF,'THAN # OF DAYS IN SPECIFIED MONTH',CR,LF,EOM
LEAP_YR DW 0
YEAR DW 0
MONTH DW 0
DAY DW 0
WEEK_DY DW 0
XLAT_MONTH DB 31,28,31 ;JAN,FEB,MAR
DB 30,31,30 ;APR,MAY,JUN
DB 31,31,30 ;JUL,AUG,SEP
DB 31,30,31 ;OCT,NOV,DEC
DB 29 ;FEB IN LEAP YEAR
DATA ENDS
DGROUP GROUP DATA
CODE SEGMENT 'CODE'
ASSUME CS:CODE,DS:DGROUP,SS:DGROUP
PUBLIC WEEKDY
WEEKDY PROC FAR
PUSH BP ; SAVE FRAME POINTER
PUSH AX ; SAVE REGISTERS
PUSH BX
PUSH DX
MOV BP,SP ; FRAME POINTER POINTS TO STACK PTR
MOV WEEK_DY,INITIAL_DAY ; SETUP INITIAL VALUES
MOV LEAP_YR,LEAP_YEAR_OFF
LES BX,DWORD PTR[BP+24] ; ES:BX POINTS TO MONTH
MOV AX,[BX] ; GET MONTH INTO AX
MOV MONTH,AX ; STORE MONTH
LES BX,DWORD PTR[BP+20] ; ES:BX POINTS TO DAY
MOV AX,[BX] ; GET DAY IN AX
MOV DAY,AX ; STORE DAY
LES BX,DWORD PTR[BP+16] ; ES:BX POINTS TO YEAR
MOV AX,[BX] ; GET YEAR INTO AX
MOV YEAR,AX ; STORE YEAR
CMP AX,INITIAL_YEAR ; COMPARE YEAR WITH THE LOWEST WE
; CAN PROCESS
JAE GOOD_LOW ; JUMP IF GOOD YEAR
JMP ERROR_YR ; JUMP TO ERROR IF TOO LOW A YEAR
GOOD_LOW:
CMP AX,MAX_YEAR ; COMPARE YEAR WITH THE HIGHEST WE
; CAN PROCESS
JBE GOOD_YEAR ; JUMP IF YEAR IN OUR RANGE OF CALC
JMP ERROR_YR ; JUMP TO ERROR IF TOO HIGH A YEAR
GOOD_YEAR:
MOV BX,4 ; LEAP YEAR DIVISOR
MOV DX,0
DIV BX ; DIVIDE YEAR BY 4
CMP DX,0 ; IS REMAINDER 0 ?
JNE NOT_LEAP_REQ ; JUMP IF NOT LEAP YEAR
MOV LEAP_YR,LEAP_YEAR_ON ; SET LEAP YEAR FLAG SINCE REQUEST
; IS LEAP YEAR
; -------------------------------------------------------------------
; PROCESS YEAR
; -------------------------------------------------------------------
NOT_LEAP_REQ:
MOV AX,INITIAL_YEAR ; PUT START YEAR IN AX
CHK_YR:
CMP AX,YEAR ; IS AX EQUAL TO REQUESTED YEAR
JE CHK_MONTH ; IF YES CHECK DAY COUNT
PUSH AX ; SAVE THE WORKING YEAR
MOV BX,4 ; LEAP YEAR DIVISOR
MOV DX,0
DIV BX ; DIVIDE YEAR BY 4
MOV AX,365 ; 365 DAYS/YR IN AX
CMP DX,0 ; IS REMAINDER 0 ?
JNE NOT_LEAP_YR ; JUMP IF NOT LEAP YEAR
INC AX ; INCREMENT AX IF LEAP YEAR-366 DY
NOT_LEAP_YR:
MOV BX,7 ; DAY OF WEEK DIVISOR
MOV DX,0
DIV BX ; DIVIDE TO GET WEEKDAY OFFSET
; IN DX
ADD DX,WEEK_DY ; ADD CURRENT DAY OF WEEK TO
; WEEKDAY OFFSET
CMP DX,8 ; IS IT GREATER THAN 7 ?
JL OK_DAY1 ; NO THEN OK
SUB DX,7 ; YES THEN SUBTRACT 7
OK_DAY1:
MOV WEEK_DY,DX ; SAVE RESULTING DAY OF WEEK
POP AX ; GET BACK VALUE OF AX
INC AX ; ADD 1 TO AX FOR NEXT YEAR
JMP CHK_YR ; DO AGAIN
; -------------------------------------------------------------------
; PROCESS MONTH
; -------------------------------------------------------------------
CHK_MONTH:
MOV AX,1 ; PUT START MONTH IN AX
CMP MONTH,AX ; CHECK IF MONTH < 0
JAE CHK_MO ; JUMP IF OK
JMP ERROR_MO ; JUMP IF ERROR
CHK_MO:
CMP AX,MONTH ; IS AX EQUAL TO REQUESTED YEAR
JE CHK_DAY ; IF YES CHECK DAY COUNT
PUSH AX ; SAVE THE WORKING YEAR
CMP AX,2 ; ARE WE COMPUTING FEBRUARY DAYS ?
JNE NO_FEBRUARY ; NO - JUMP OVER
CMP LEAP_YR,0 ; YES - IS LEAP YEAR FLAG SET ?
JZ NO_FEBRUARY ; NO - JUMP OVER
ADD AX,11 ; ADD AX WITH OFFSET FOR TRANSLATE
NO_FEBRUARY:
LEA BX,XLAT_MONTH ; BX POINTS TO TRANSLATE TABLE
DEC AX ; CORRECT AX FOR TABLE START
XLAT XLAT_MONTH ; TRANSLATE - AX HAS DAYS IN MONTH
MOV BX,7 ; DAY OF WEEK DIVISOR
MOV DX,0
DIV BX ; DIVIDE TO GET WEEKDAY OFFSET
; IN DX
ADD DX,WEEK_DY ; ADD CURRENT DAY OF WEEK TO
; WEEKDAY OFFSET
CMP DX,8 ; IS IT GREATER THAN 7 ?
JL OK_DAY2 ; NO THEN OK
SUB DX,7 ; YES THEN SUBTRACT 7
OK_DAY2:
MOV WEEK_DY,DX ; SAVE RESULTING DAY OF WEEK
POP AX ; GET BACK VALUE OF AX
INC AX ; ADD 1 TO AX FOR NEXT MONTH
JMP CHK_MO ; DO AGAIN
; -------------------------------------------------------------------
; PROCESS DAY
; -------------------------------------------------------------------
CHK_DAY:
CMP AX,2 ; ARE WE ASKING FOR FEBRUARY DAYS ?
JNE NOT_IN_FEB ; NO - JUMP OVER
CMP LEAP_YR,0 ; YES - IS LEAP YEAR FLAG SET ?
JZ NOT_IN_FEB ; NO - JUMP OVER
ADD AX,11 ; ADD AX WITH OFFSET FOR TRANSLATE
NOT_IN_FEB:
LEA BX,XLAT_MONTH ; BX POINTS TO TRANSLATE TABLE
DEC AX ; CORRECT AX FOR TABLE START
XLAT XLAT_MONTH ; TRANSLATE - AX HAS DAYS IN MONTH
CMP DAY,AX ; BE SURE DAY NOT > DAYS IN MONTH
JA ERROR_DY ; JUMP IF ERROR
MOV AX,DAY ; PUT REQUESTED DAY IN AX
MOV BX,7 ; DAY OF WEEK DIVISOR
MOV DX,0
DIV BX ; DIVIDE TO GET WEEKDAY OFFSET
; IN DX
ADD DX,WEEK_DY ; ADD CURRENT DAY OF WEEK TO
; WEEKDAY OFFSET
CMP DX,8 ; IS IT GREATER THAN 7 ?
JL OK_DAY3 ; NO THEN OK
SUB DX,7 ; YES THEN SUBTRACT 7
OK_DAY3:
MOV WEEK_DY,DX ; SAVE RESULTING DAY OF WEEK
; -------------------------------------------------------------------
; WE NOW KNOW WHAT DAY OF THE WEEK IT IS
; -------------------------------------------------------------------
LES BX,DWORD PTR[BP+12] ; ES:BX POINTS TO RETURN VALUE
; FOR DAY OF WEEK
MOV AX,WEEK_DY ; GET DAY OF WEEK INTO AX
MOV [BX],AX ; STOW IT FOR RETURN
JMP BYE ; JUMP OVER ERROR REPORTS
ERROR_YR:
LEA DX,ERR_MSG_YR ; BAD YEAR ERROR MESSAGE
JMP MESSAGE
ERROR_MO:
LEA DX,ERR_MSG_MO ; BAD MONTH ERROR MESSAGE
JMP MESSAGE
ERROR_DY:
LEA DX,ERR_MSG_DY ; BAD DAY ERROR MESSAGE
MESSAGE:
PUSH DX ; SAVE ERROR MSG ADDRESS
LEA DX,ERR_MSG_HDR ; DX POINTS TO ERROR MSG HEADER
MOV AX,0900H ; LOAD AX WITH PRINT FUNCTION
INT 21H ; PRINT MESSAGE
POP DX ; RESTORE ERROR MSG ADDRESS
MOV AX,0900H ; LOAD AX WITH PRINT FUNCTION
INT 21H ; PRINT MESSAGE
BYE:
POP DX ; RESTORE REGISTERS
POP BX
POP AX
POP BP ; RESTORE FRAME POINTER
RET 16 ; RETURN AND POP 16 BYTES OFF
; STACK
WEEKDY ENDP
CODE ENDS
END